<template>
  <div class="s-table-wrapper">
    <div class="s-search-condition-container" v-if="showSearch">
      <input-list-view :items="conditions" :horizontal="true" :collapseTags="collapseTags" :filterable="filterable" :showSearch="showSearchButton" @on-search="search" @on-change-date="changeDate" @on-change-year="changeYear" @on-change-option="changeOption" @on-change-multi-option="changeMultiOption" >
      </input-list-view>
    </div>
    <div class="s-table-operate-button-group">
      <slot></slot>
    </div>
    <div class="s-table-container">
      <el-table :data="data" ref="multipleTable" style="width: 100%" :max-height="maxHeight" :default-sort="defaultSort" :stripe="stripe" :border="border" :size="size" :row-key="getRowKeys" @selection-change="selectChange" @sort-change="sortChange" @select="select" @select-all="selectAll" @cell-mouse-enter="cellMouseEnter" @cell-mouse-leave="cellMouseLeave" @cell-click="cellClick"  @cell-dblclick="cellDblClick" @row-click="rowClick" @row-contextmenu="rowContextMenu" @row-dblclick="rowDblClick" @header-click="headerClick" @header-contextmenu="headerContextMenu" @filter-change="filterChange" @current-change="currentChange" @header-dragend="headerDragend" @expand-change="expandeChange">
        <!--多选框checkbox-->
        <el-table-column type="selection" :reserve-selection="true" width="42" v-if="canCheck" :selectable="disabledSelection"></el-table-column>
        <el-table-column  v-if="showIndex"  type="index" width="60" :index="indexMethod" label="序号" > </el-table-column>
        <!--数据列-->
        <el-table-column v-for="(col,index) in columns" :prop="col.field" v-if="!col.hidden" :label="col.header" :sortable="col.sortable" :key="index" :width="col.header == '序号' && 100">
          <template slot-scope="scope">
            <!-- 纯文本，或者代码 -->
             <!-- 显示title，如果有hoverTitleText字段，则显示该字段的值，没有则显示单元格内的内容 -->
            <div class="cell-normal-value" :title="scope.row.hoverTitleText ? scope.row.hoverTitleText :scope.row[col.field]" v-if="!cellEditable && showHoverTitle" v-html='scope.row[col.field]'> {{scope.row[col.field]}}</div>
            <!-- 不显示title -->
            <div class="cell-normal-value" v-if="!cellEditable && !showHoverTitle " v-html='scope.row[col.field]'> {{scope.row[col.field]}} </div>
            <!-- 可编辑 -->
            <div class="cell-edit-value" v-if="cellEditable">
              <div class="" v-if="col.type == 'text'">
                <el-input type="text" size="small" v-model="scope.row[col.field]" clearable v-bind:style="{width:'100%'}"></el-input>
              </div>
              <div class="" v-else-if="col.type == 'checkbox'">
                <el-checkbox v-model="scope.row[col.field]"  v-if="!scope.row.hideCellCheck" :disabled="scope.row.disabledCellCheck" @change="cellChange('check',scope.$index,col,scope.row,$event)"></el-checkbox>
              </div>
              <div class="" v-else-if="col.type == 'switch'">
                <el-switch v-model="scope.row[col.field]" active-color="#13ce66" inactive-color="#ff4949" v-if="!scope.row.hideCellCheck" :disabled="scope.row.disabledCellCheck" @change="cellChange('switch',scope.$index, scope.row,col.field,$event)"></el-switch>
              </div>
              <div class="" v-if="col.type == 'number'">
                <el-input-number v-model="scope.row[col.field]" size="small" controls-position="right"  v-if="!scope.row.hideCellCheck" :disabled="scope.row.disabledCellCheck" :style="{width:'160px'}" @change="cellChange('number',scope.$index, scope.row,col.field,$event)"></el-input-number>
                <span>{{scope.row[col.field]}}</span>
              </div>
            </div>
          </template>
        </el-table-column>
        <!--操作列-->
        <el-table-column label="操作" v-if="showOperate" :width="100*buttonCount">
          <template slot-scope="scope">
            <!--直接传operateButtons，操作列的按钮全相同-->
            <div class="operate-button-column" v-if="!scope.row.operateButtons || scope.row.operateButtons.length == 0">
              <el-button  size="mini" v-for="(btn,i) in operateButtons" :key="i"  @click="handleOperate(btn,scope.$index, scope.row)">{{btn}}</el-button>
            </div>
            <!--在row数据中传operateButtons，可实现操作列每行的按钮不同-->
            <div class="operate-button-column" v-if="scope.row.operateButtons && scope.row.operateButtons.length != 0">
              <el-button  size="mini" v-for="(btn,i) in scope.row.operateButtons"  :key="i" @click="handleOperate(btn,scope.$index, scope.row)">{{btn}}</el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <div class="s-table-paginator" v-if="showPaginator">
      <div class="pagination-container">
        <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" @prev-click="preClick"
                       @next-click="nextClick" :current-page="currentPage" :page-sizes="[5,10,15, 20,25,30]" :page-size="currentSize"
                       layout="prev, pager, next, jumper , sizes , total" :total="total">
        </el-pagination>
      </div>
    </div>
  </div>
</template>

<script>
  import InputListView from '../InputListView/InputListView.vue'

  export default {
    name: 'TableView',
    components: {
      InputListView
    },
    props: {
      //表头数据
      cols: {
        type: Array,
        default: function () {
          return [];
        }
      },
      //表格数据
      tableData: {
        type: Array,
        default: function () {
          return [];
        }
      },
      //是否显示悬浮文字 默认不显示
      showHoverTitle: {
        type: Boolean,
        default: false
      },
      //是否显示序号列
      showIndex: {
        type: Boolean,
        default: false
      },
      //是否显示查询条件
      showSearch: {
        type: Boolean,
        default: false
      },
      //是否显示查询按钮，默认显示，如果还有在slot中添加其他按钮，可能会造成查询按钮和添加的按钮不在一行，此时可以将默认显示的查询按钮隐藏
      showSearchButton: {
        type: Boolean,
        default: true
      },
      //搜索条件
      searchCondition: {
        type: Array,
        default: function () {
          return [];
        }
      },
      //表格单元格是否是可编辑的
      cellEditable: {
        type: Boolean,
        default: false
      },
      //** Table 的高度，默认为自动高度。如果 height 为 number 类型，单位 px；如果 height 为 string 类型，则这个高度会设置为 Table 的 style.height 的值，Table 的高度会受控于外部样式。
      height: {
        type: null,
        default: 'auto'
      },
      //** Table 的最大高度。合法的值为数字或者单位为 px 的高度。
      maxHeight: {
        type: null,
        default: 'auto'
      },
      //是否为隔行变色 table
      stripe: {
        type: Boolean,
        default: true
      },
      //是否带有纵向边框
      border: {
        type: Boolean,
        default: true
      },
      //Table 的尺寸    medium / small / mini
      size: {
        type: String,
        default: 'medium'
      },
      //** 列的宽度是否自撑开
      fit: {
        type: Boolean,
        default: true
      },
      //** 是否要高亮当前行
      'highlight-current-row': {
        type: Boolean,
        default: false
      },
      //** 空数据时显示的文本内容，也可以通过 slot="empty" 设置
      'empty-text': {
        type: String,
        default: '暂无数据'
      },
      //** 是否默认展开所有行，当 Table 包含展开行存在或者为树形表格时有效
      'default-expand-all':{
        type: Boolean,
        default: false
      },
      //** 可以通过该属性设置 Table 目前的展开行，需要设置 row-key 属性才能使用，该属性为展开行的 keys 数组。
      'expand-row-keys':{
        type: Array,
        default: function(){
          return [];
        }
      },
      //** 默认的排序列的 prop 和顺序。它的prop属性指定默认的排序的列，order指定默认排序的顺序  ascending, descending   如果只指定了prop, 没有指定order, 则默认顺序是ascending
      'default-sort':{
        type: Object,
        default: function(){
          return {order:'ascending'};
        }
      },
      //** tooltip effect 属性  dark/light
      'tooltip-effect': {
        type: String,
        default: 'light'
      },
      //** 合计行第一列的文本
      'sum-text': {
        type: String,
        default: '合计'
      },
      //** 是否在表尾显示合计行
      'show-summary': {
        type: Boolean,
        default: false
      },
      //** 自定义的合计计算方法
      'summary-method': {
        type: Function,
        default: function(){
          return null;
        }
      },
      //** 合并行或列的计算方法
      'span-method': {
        type: Function,
        default: function(){
          return null;
        }
      },
      //** 在多选表格中，当仅有部分行被选中时，点击表头的多选框时的行为。若为 true，则选中所有行；若为 false，则取消选择所有行
      'select-on-indeterminate': {
        type: Boolean,
        default: true
      },
      //** 展示树形数据时，树节点的缩进
      indent: {
        type: Number,
        default: 16
      },
      //** 是否懒加载子节点数据
      lazy: {
        type: Boolean,
        default: false
      },
      //** 加载子节点数据的函数，lazy 为 true 时生效，函数第二个参数包含了节点的层级信息
      load: {
        type: Function,
        default: function(){
          return null;
        }
      },
      //** 渲染嵌套数据的配置选项
      'tree-props': {
        type: Object,
        default: function(){
          return 	{ hasChildren: 'hasChildren', children: 'children' };
        }
      },
      //表格是否显示checkbox
      canCheck: {
        type: Boolean,
        default: false
      },
      //是否开启checkbox部分禁用
      disabledPartialCheck: {
        type: Boolean,
        default: false
      },
      //开启checkbox部分禁用后，以什么值来判断是可用的
      disabledPartialLabel: {
        type: String,
        default: ''
      },
      //开启checkbox部分禁用后，以什么key来判断是可用的
      disabledPartialKey: {
        type: String,
        default: ''
      },
      //是否显示分页
      showPaginator: {
        type: Boolean,
        default: false
      },
      //分页 当前页
      pageNumber: {
        type: Number,
        default: 1
      },
      //分页 当前每页显示的数据条数
      pageSize: {
        type: Number,
        default: 5
      },
      //总记录数
      totalRecords: {
        type: Number,
        default: 0
      },
      //分页按钮显示配置及布局
      layout:{
        type: String,
        default:'prev, pager, next, jumper , sizes , total'
      },
      //表格默认排序项
      defaultSort: {
        type: Object,
        default: function () {
          return {}
        }
      },
      //选中项
      checkedRows: Array,
      //是否清除选中项
      clearSelect: {
        type: Boolean,
        default: false
      },
      //显示几倍100px，来判断操作列显示多宽
      buttonCount: {
        type: Number,
        default: 0
      },
      //是否显示操作列
      showOperate: {
        type: Boolean,
        default: false
      },
      //默认操作按钮显示
      operateButtons: {
        type: Array,
        default: function () {
          return [];
        }
      },
      collapseTags: {
        type: Boolean,
        default: false
      }, // 多选时是否将选中值按文字的形式展示
      filterable: {
        type: Boolean,
        default: false
      }, // 下拉框、多选下拉框、级联框可搜索
    },
    data: function () {
      return {
        columns: [],
        data: [],
        currentPage: 1,
        currentSize: 10,
        total: 0,
        conditions: [],
        clearSelectedData: false,
      }
    },
    watch: {
      cols: {
        handler: function (val) {
          if (val && val.length != 0) {
            this.columns = val;
            if (this.columns && this.columns.length != 0) {
              this.data = this.data.map((d) => {
                let obj = this.cloneObj(d);
                obj.metaCopyValue = {};
                this.columns.forEach((col) => {
                  if (col.type == 'select' && col.option && col.option.length != 0) {
                    obj.metaCopyValue[col.field] = d[col.field];
                    let option = col.option.filter((op) => {
                      if (!this.isEmpty(d[col.field])) {
                        if (d[col.field].textColor) {
                          return d[col.field].text == op.value;
                        } else {
                          return d[col.field] == op.value;
                        }
                      }
                    });
                    option.length > 0 && (obj[col.field].textColor ? (obj[col.field].text = option[0].label) : (obj[col.field] = option[0].label));
                  }
                })
                return obj;
              })
            }
          } else {
            this.columns = [];
          }
        },
        immediate: true,
        deep:true
      },
      tableData: {
        handler: function (val) {
          if (this.columns && this.columns.length != 0) {
            this.data = val.map((d) => {
              let obj = this.cloneObj(d);
              obj.metaCopyValue = {};
              this.columns.forEach((col) => {
                if (col.type == 'select' && col.option && col.option.length != 0) {
                  obj.metaCopyValue[col.field] = d[col.field];
                  let option = col.option.filter((op) => {
                    if (!this.isEmpty(d[col.field])) {
                      if (d[col.field].textColor) {
                        return d[col.field].text == op.value;
                      } else {
                        return d[col.field] == op.value;
                      }
                    }
                  });
                  option.length > 0 && (obj[col.field].textColor ? (obj[col.field].text = option[0].label) : (obj[col.field] = option[0].label));
                }
              })
              return obj;
            })
          } else {
            this.data = val;
          }
        },
        immediate: true,
        deep:true
      },
      pageNumber: {
        handler: function (val) {
          val && (this.currentPage = val);
        },
        immediate: true
      },
      pageSize: {
        handler: function (val) {
          val && (this.currentSize = val)
        },
        immediate: true
      },
      clearSelect: {
        handler: function (val) {
          if (val) {
            this.$refs.multipleTable.clearSelection();
          }
        },
        immediate: true
      },
      totalRecords: {
        handler: function (val) {
          this.total = val
        },
        immediate: true
      },
      checkedRows: {
        handler: function (val) {
          let me = this;
          if (val == undefined) {
            return;
          } else if (val) {
            if (val.length != 0) {
              val.forEach((d) => {
                this.$nextTick(() => {
//                  console.log('toggle selection', d);
                  me.$refs.multipleTable.toggleRowSelection(d, true);
                })
              })
            } else {
              this.$nextTick(() => {
//                console.log('toggle clear');
                me.$refs.multipleTable.clearSelection();
              })
            }
          } else {
            this.$nextTick(() => {
//              console.log('clear selection');
              me.$refs.multipleTable.clearSelection();
            })
          }
        },
        immediate: true
      },
      searchCondition: {
        handler: function (val) {
          this.conditions = val;
        },
        immediate: true
      },
    },
    mounted: function () {
      this.currentSize = this.pageSize;
    },
    methods: {
//      表格相关事件
      getRealTableData(cols, tableData,) {
        if (cols && cols.length != 0) {
          this.data = val.map((d) => {
            let obj = this.cloneObj(d);
            this.columns.every((col) => {
              if (col.type == 'select' && col.option && col.option.length != 0) {
                let option = col.option.filter((op) => {
                  return d[col.field] == op.value;
                });
                obj[col.field] = option[0].label;
                return false;
              } else {
                return true;
              }
            })
            return obj;
          })
        }
      },
      // 获取row的key值
      getRowKeys(row) {
        return row.id;
      },
      //设置序号
      indexMethod(i){
        return this.pageSize*(this.currentPage - 1) + i+ 1;
      },
      //当选择项发生变化时会触发该事件
      selectChange(selection) {
         console.log('selectChange事件',selection);
        this.$emit('selection-change', selection);
      },
      //当用户手动勾选数据行的 Checkbox 时触发的事件
      select(selection, row) {
        console.log('select事件',selection, row);
        this.$emit('select', {selection:selection,row:row});
      },
      //当用户手动勾选全选 Checkbox 时触发的事件
      selectAll(selection) {
        this.$emit('select-all', selection);
      },
      //当单元格 hover 进入时会触发该事件
      cellMouseEnter(row, column, cell, event) {
        this.$emit('cell-mouse-enter', {row, column, cell, event});
      },
      //当单元格 hover 退出时会触发该事件
      cellMouseLeave(row, column, cell, event) {
        this.$emit('cell-mouse-leave', {row, column, cell, event});
      },
      //当某个单元格被点击时会触发该事件
      cellClick(row, column, cell, event) {
        this.$emit('cell-click', {row, column, cell, event});
      },
      //当某个单元格被双击击时会触发该事件
      cellDblClick(row, column, cell, event) {
        this.$emit('cell-dblclick', {row, column, cell, event});
      },
       //当某一行被点击时会触发该事件
      rowClick(row, column, event) {
        this.$emit('row-click', {row, column,  event});
      },
      //当某一行被鼠标双击时会触发该事件
      rowDblClick(row, column,  event) {
        this.$emit('row-dblclick', {row, column, event});
      },
      //当某一行被鼠标右键点击时会触发该事件
      rowContextMenu(row, column,  event) {
        this.$emit('row-contextmenu', {row, column,  event});
      },
       //当某一列的表头被点击时会触发该事件
      headerClick(column, event) {
        this.$emit('header-click', { column, event});
      },
      //当某一列的表头被鼠标右键点击时触发该事件
      headerContextMenu(column, event) {
        this.$emit('header-contextmenu', {column, event});
      },
      //当表格的筛选条件发生变化的时候会触发该事件，参数的值是一个对象，对象的 key 是 column 的 columnKey，对应的 value 为用户选择的筛选条件的数组
      filterChange(filters) {
        this.$emit('filter-change', filters);
      }, 
      //当表格的当前行发生变化的时候会触发该事件，如果要高亮当前行，请打开表格的 highlight-current-row 属性
      currentChange(currentRow, oldCurrentRow) {
        this.$emit('current-change', {currentRow, oldCurrentRow});
      },
      //当拖动表头改变了列的宽度的时候会触发该事件
      headerDragend(newWidth, oldWidth, column, event) {
        this.$emit('header-dragend', {newWidth, oldWidth, column, event});
      },
      //当用户对某一行展开或者关闭的时候会触发该事件（展开行时，回调的第二个参数为 expandedRows；树形表格时第二参数为 expanded）
      expandeChange(row,expandedRows) {
        this.$emit('expand-change', {row,expandedRows});
      },
      sortChange(e) {
        this.$emit('sort-change', e);
      },
      handleSizeChange(size) {
        this.currentSize = size;
        this.currentPage = 1;
        this.$emit('size-change', size);
      },
      handleCurrentChange(currentPage) {
        this.currentPage = currentPage;
        this.$emit('current-page-change', currentPage);
      },
      preClick(currentPage) {
        this.currentPage = currentPage;
        this.$emit('pre-click', currentPage);
      },
      nextClick(currentPage) {
        this.currentPage = currentPage;
        this.$emit('next-click', currentPage);
      },
      //查询相关事件导出
      search(e) {
        this.$emit('on-search', e);
      },
      changeDate(date) {
        this.$emit('on-change-date', date)
      },
      changeYear(year) {
        this.$emit('on-change-year', year)
      },
      changeOption(e) {
        this.$emit('on-change-option', e)
      },
      changeMultiOption(e) {
        this.$emit('on-change-multi-option', e)
      },
      disabledSelection(row, index){
        if (this.disabledPartialCheck) {
          if (row[this.disabledPartialKey] == this.disabledPartialLabel) {
            return !0;
          } else {
            return !1;
          }
        } else {
          return !0;
        }
      },
      cellChange(cellType,index,col,row){
        this.$emit('cell-change', {cellType:cellType, index: index, col: col, row: row,cellParam:arguments.slice(4) });
      },
      //操作列按钮事件导出
      handleOperate(btn,index, row) {
        this.$emit('on-operate', {
          btnText:btn,
          index: index,
          row: row
        })
      },
    }
  }
</script>

<style rel="stylesheet/scss" lang="scss" scoped>
  @import "../../../assets/styles/base_style";

  .s-table-wrapper {
    .s-search-condition-container {
      margin-bottom: 5px;
    }
    .s-table-operate-button-group:after {
      @include clearFloat;
    }
    .s-table-operate-button-group {
      /*margin:20px 0;*/
    }
    .s-table-container:after {
      @include clearFloat;
    }
    .s-table-container {
      .required-icon {
        float: left;
        width: 10px;
        padding-left: 5px;
        padding-top: 5px;
        color: red;
        /*font-size: 1.4rem;*/
        font-size: 22px;
      }
    }
  }
</style>
<style rel="stylesheet/scss" lang="scss">
  @import "../../../assets/styles/base_style";

  .s-table-wrapper {
    .s-table-paginator {
      @include paginator;
      .el-button {
        margin: 0 5px;
      }
    }
    .s-table-container {
      @include elTableFormat;
      @include elButtonFormatForTable;
    }
    .el-table th { display: table-cell !important; }
    .el-table--scrollable-x .el-table__body-wrapper{
      overflow-x: auto;
      @include scrollbarStyle(8px,8px,transparent,#CECECE);
    }
  }
</style>
